#ifndef PLAYER_H
#define PLAYER_H

#include "Actor.h"
#include "MissileObject.h"

class Sword;
typedef boost::shared_ptr<Sword> SwordPtr;

// some constants handling caps
// TODO: create xml for settings like this.
static const float mMaxEXP = 1000.0f;
static const float maxSkillsProBar = 10.0f;  // THIS MUST BE CHANGED IN GUI TOO ! (in case you modifiy it) ,  no?
static const float skillBarrier = 3.0f;

// some constants handling stat gain per skillpoint
static const float healthGain = 20.0f;
static const float energyGain = 10.0f;
static const float combatGain = 1.f;

/* Combat class of player */
enum Archetype
{
	ARCHE_NONE = 0,
	ARCHE_MELEE = 1,
	ARCHE_RANGED = 2
};

/* available skilltrees. */
enum Tree
{
	TREE_HEALTH,
	TREE_ENERGY,
	TREE_COMBAT
};

/* SkillTree.  Amount of points spent per tree and the selected archetype(character class) */
struct SkillTree
{
	SkillTree(float health = 0.0f,
			  float energy = 0.0f,
			  float combat = 0.0f,
			  Archetype arch = ARCHE_NONE)
		: healthTree(health), energyTree(energy), combatTree(combat), archetype(arch) { }

	float healthTree;
	float energyTree;
	float combatTree;
	
	Archetype archetype;
};

class Player :
	public Actor
{
public:
	Player();
	Player(std::string id);
	~Player(void);

	void incSkillPoints();
	void decSkillPoints();
	void incEXP(float amount);
	bool buySkill(Tree tree);
	bool skillAble(Tree tree);
	void changeClass(Archetype arch);
	virtual void collision(BaseObjectPtr obj, btVector3 &point);
	const char getLevelPower() const;
	void setLevelPower(const char power);

	const float getSkillPoints(void) const;
	const float getEXP(void) const;
	const unsigned int getCurrentLevel(void) const;
	void setCurrentLevel(const unsigned int level);
	void setSkillPoints(const float sp);
	void setEXP(const float exp);
	boost::shared_ptr<SkillTree> getSkillTree();

	void normalAttack(void);
	void collectOrb(RewardType type, float amount);
	void block(void);
	void unblock(void);
	void prepareShoot(void);
	void shoot(void);
	void equipSword(std::string id = "level/sword.xml");
	void removeSword(void);
	void equipGun(std::string id = "level/gun.xml");
	void removeGun(void);
	void equipShield(std::string id = "level/shield.xml");
	void removeShield(void);
	void validateStats();
	virtual void update(const unsigned long elapsedTime);
	
	virtual void recieveDmg(const btVector3 &pos, const float dmg);
	virtual void knockBack(btVector3 &dir);
	virtual void stun(const float dur);
	virtual void moveLeft(void);
	virtual void moveRight(void);
	virtual void jump(void);

	unsigned int mFlyingTime;
	float mLockControls;
	bool dontKill;

protected:
	void readPlayerFromXML();
	void savePlayerToXML();
	void executeCombo(float cost, float dmgBoost, float stun, float knockBack);
	void swordToHand(void);
	void swordToBack(void);

	float mSP, mEXP;
	boost::shared_ptr<SkillTree> mpSkills;
	
	SwordPtr sword;
	SwordPtr shield;
	SwordPtr gun;
	Ogre::SceneNode *mpGunParticle;
	MissileObjectPtr mpCopyMissile;
	MissileObjectPtr mpMissile;
	float mNextDirection;
	bool mSwordInHand;
	bool mGunLoaded;
	unsigned long mPrepareTime;
	unsigned long mPrepareTimeElapsed;
	unsigned long mNoBGTime;
	unsigned long mBlockTime;
	unsigned int mJumpCounter;
	float mShootPos;
	bool mPlayAnim;
	bool mPlus;
	char mLevelPower;
	unsigned int mCurrentLevel;
};

typedef boost::shared_ptr<Player> PlayerPtr;
#endif